#include "gtest/gtest.h"
#include "List02.hpp"
#define NUM(x, y)       ((sizeof(x)) / sizeof(y))
TEST(spliceTest,  functions)
{
	List<int>	lst1, lst2;
	List<int>::iterator it;

	for (int i = 1; i <= 4; ++i)
		lst1.push_back(i);

	for (int i = 1; i <= 3; ++i)
		lst2.push_back(i * 10);

	it = lst1.begin();
	++it;

	EXPECT_EQ(*it, 2);

	lst1.splice(it, lst2);
	int arr1[] = {1, 10, 20, 30, 2, 3, 4};
	List<int>::iterator pos = lst1.begin();
	for (size_t i = 0; i < sizeof(arr1) / sizeof(int); ++i)
		EXPECT_EQ(*pos++, arr1[i]);	
	EXPECT_EQ(lst2.size(), 0u);


	lst2.splice(lst2.begin(), lst1, it);
	EXPECT_EQ(*lst2.begin(), 2);
	
	it = lst1.begin();
	++it, ++it, ++it;

	lst1.splice(lst1.begin(), lst1, it , lst1.end());
	int arr2[] = {30, 3, 4, 1, 10, 20};
	pos = lst1.begin();
	for (size_t i = 0; i < sizeof(arr2) / sizeof(int); ++i)
		EXPECT_EQ(*pos++, arr2[i]);	

}

TEST(removeTest, content)
{
	int arr[] = { 1, 33, 2, 33, 33, 3, 33,4};
	List<int> lst(arr, arr + sizeof(arr) / sizeof(int));

	lst.remove(33);
	List<int>::iterator it = lst.begin();
	for (int i = 1; i < 5; ++i)
		EXPECT_EQ(*it++, i);
}

bool double_digit ( const int & value) {return (value >= 10);}

class isOdd {
public:
		bool operator() (const int& value)  { return (value % 2) == 1;}
};

TEST(removeIfTest, contents)
{
	int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
	List<int> lst(arr, arr + sizeof(arr) / sizeof(int));

	EXPECT_EQ(lst.size(), 12u);
	lst.remove_if(double_digit);
	EXPECT_EQ(lst.size(), 9u);

	lst.remove_if(isOdd());


	List<int>::iterator it = lst.begin();
	for (int i = 2; i < 10; i += 2)
		EXPECT_EQ(*it++, i);
}

TEST(resverseTest, contents)
{
	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9};
	List<int> lst(arr, arr + NUM(arr, int));

	EXPECT_EQ(lst.size(), 9u);
	lst.reverse();
	List<int>::iterator it = lst.begin();
	for (int i = 9; i > 0; --i)
		EXPECT_EQ(*it++, i);
}

TEST(uniqueTest, content)
{
	List<int> lst;

	lst.unique();
	
	int arr[] = {1, 2, 2, 3, 3, 4, 4,5, 4, 5, 5, 6};
	int arr2[] = {1, 2, 3, 4, 5, 4, 5, 6 };

	lst.assign(arr, arr + NUM(arr, int));
	lst.unique();
	List<int>::iterator it = lst.begin();
	for(size_t i = 0; i < NUM(arr2, int); ++i)
		EXPECT_EQ(*it++, arr2[i]);
}

bool myComparison (double first, double second)
{
	return (int (first) < int (second));
}

TEST(mergeTest, contents)
{
	double arr1[] = {2.2, 2.9, 3.1};
	double arr2[] = {1.4, 3.7, 7.1};
	List<double> first(arr1, arr1 + NUM(arr1, double)), 
		second(arr2, arr2 + NUM(arr2, double));
	List<double>::iterator it;
	
	double res1[] = {1.4, 2.2, 2.9, 3.1, 3.7,  7.1};
	double res2[] = {1.4, 2.2, 2.9, 2.1, 3.1,  3.7, 7.1};

	first.merge(second);
	it = first.begin();
	EXPECT_EQ(first.size(), 6u);
	for (size_t i = 0; i < NUM(res1, double); ++i)
		EXPECT_EQ(*it++, res1[i]);	

	second.push_back(2.1);
	first.merge(second, myComparison);

	EXPECT_EQ(first.size(), 7u);
	it = first.begin();
	for (size_t i = 0; i < NUM( res2, double); ++i)
		EXPECT_EQ(*it++, res2[i]);
}

TEST(sortTest, contents)
{
	int arr[] = {5, 4, 3, 2, 1};
	List<int> lst(arr, arr + NUM(arr, int));

	lst.sort();
	List<int>::iterator it = lst.begin();
	for (int i = 1; i < 6; ++i)
		EXPECT_EQ(*it++, i);
}

bool myComp (int first, int second)
{
	return ( (first) >  (second));
}


TEST(sortTest, function)
{
	int arr[] = {1, 2, 3, 4, 5};
	List<int> lst(arr, arr + NUM(arr, int));

	lst.sort(myComp);
	List<int>::iterator it = lst.begin();
	for (int i = 5; i > 0; --i)
		EXPECT_EQ(*it++, i);
}
